﻿namespace wwm.LeetCodeHelper.Infrastructure;

/// <summary>
/// Json 序列化帮助类
/// </summary>
public static class JsonHelper
{
    /// <summary>
    /// json 转换配置
    /// </summary>
    public static JsonSerializerOptions JsonConvertOption = new JsonSerializerOptions()
    {
        AllowTrailingCommas = true,
        NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString
    };

    public static JsonElement GetSubJsonElement(this string jsonText, string propertyName)
    {
        if (string.IsNullOrWhiteSpace(jsonText)) return default;
        JsonDocument json = JsonDocument.Parse(jsonText, new JsonDocumentOptions()
        {
            AllowTrailingCommas = true
        });
        json.RootElement.TryGetProperty(propertyName, out JsonElement value);
        return value;
    }

    public static IList<JsonElement> GetSbuJsonElementArray(this string jsonText, string propertyName)
    {
        return jsonText.GetSubJsonElement(propertyName).EnumerateArray().ToList();
    }

    public static JsonElement GetSubJsonElement(this JsonElement jsonElement, string propertyName)
    {
        jsonElement.TryGetProperty(propertyName, out var value);
        return value;
    }

    public static IList<JsonElement> GetSubJsonElementArray(this JsonElement jsonElement, string propertyName)
    {
        return jsonElement.GetProperty(propertyName).EnumerateArray().ToList();
    }

    /// <summary>
    /// 获取json对象的属性值
    /// </summary>
    /// <param name="jsonText"></param>
    /// <param name="propertyName"></param>
    /// <returns></returns>
    public static T GetJsonObjectProperty<T>(this string jsonText, string propertyName)
    {
        if (string.IsNullOrWhiteSpace(jsonText)) return default;
        using JsonDocument json = JsonDocument.Parse(jsonText, new JsonDocumentOptions()
        {
            AllowTrailingCommas = true
        });
        json.RootElement.TryGetProperty(propertyName, out JsonElement value);
        if (value.ValueKind == JsonValueKind.Undefined) return default;
        return GetData<T>(value);
    }

    /// <summary>
    /// 获取json数组的属性值
    /// </summary>
    /// <param name="jsonText"></param>
    /// <param name="propertyName"></param>
    /// <returns></returns>
    public static List<T> GetJsonArrayProperty<T>(this string jsonText, string propertyName = null)
    {
        if (string.IsNullOrWhiteSpace(jsonText)) return default;
        using (JsonDocument json = JsonDocument.Parse(jsonText))
        {
            var array = json.RootElement.EnumerateArray().ToList();
            var t = typeof(T);
            List<JsonElement> data;
            if (string.IsNullOrWhiteSpace(propertyName))
            {
                data = array;
            }
            else
            {
                data = array.Select(p => p.GetProperty(propertyName)).ToList();
            }
            return t.Name switch
            {
                "Int32" => data.Select(a => a.GetInt32()).Cast<T>().ToList(),
                "Double" => data.Select(a => a.ToString().ToDouble()).Cast<T>().ToList(),
                "String" => data.Select(a => a.GetString()).Cast<T>().ToList(),
                "Decimal" => data.Select(a => a.GetDecimal()).Cast<T>().ToList(),
                "DateTime" => data.Select(a => a.GetDateTime()).Cast<T>().ToList(),
                "Boolean" => data.Select(a => a.GetBoolean()).Cast<T>().ToList(),
                "Char" => data.Select(a => a.GetByte()).Cast<T>().ToList(),
                "Guid" => data.Select(a => a.GetGuid()).Cast<T>().ToList(),
                _ => null,
            };
        };
    }

    private static T GetData<T>(JsonElement json)
    {
        var t = typeof(T);
        switch (t.Name)
        {
            case "Int32":
                json.TryGetInt32(out int int32);
                return (T)(object)int32;
            case "Double":
                double d = json.ToString().ToDouble();
                return (T)(object)d;
            case "String":
                return (T)(object)json.GetString();
            case "Decimal":
                json.TryGetDecimal(out decimal dec);
                return (T)(object)dec;
            case "DateTime":
                json.TryGetDateTime(out DateTime dt);
                return (T)(object)dt;
            case "Boolean":
                return (T)(object)json.GetBoolean();
            case "Char":
                json.TryGetByte(out byte by);
                return (T)(object)by;
            case "Guid":
                json.TryGetGuid(out Guid g);
                return (T)(object)g;
            default:
                return default;
        };
    }

    /// <summary>
    /// copy复制,使用序列化反序列化方式
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="t"></param>
    /// <returns></returns>
    public static T DeepClone<T>(this T t) where T : class
    {
        if (t == null) return default;
        return JsonSerializer.Deserialize<T>(JsonSerializer.Serialize(t));
    }
}

